﻿using System;
using System.Collections.Generic;
using System.Configuration;
using YelpAPI.Objects;

namespace YelpAPI.TestClient
{
    class Program
    {
        static void Main(String[] args)
        {

            YelpServices.APIKey = ConfigurationManager.AppSettings["APIKey"];

            Console.Write("> ");
            String line = Console.ReadLine();

            while (line != null)
            {
                String[] tokens = Tokenize(line);

                if (tokens.Length > 0)
                {
                    try
                    {
                        SearchResult result = null;
                        Boolean helpCommand = false;

                        switch (tokens[0].ToLower())
                        {
                            case "box":
                                if (tokens.Length == 7)
                                {
                                    result = YelpSearchService.SearchBoundingBox(Double.Parse(tokens[1]), Double.Parse(tokens[2]), Double.Parse(tokens[3]), Double.Parse(tokens[4]), tokens[5], tokens[6]);
                                }
                                else if (tokens.Length == 6)
                                {
                                    result = YelpSearchService.SearchBoundingBox(Double.Parse(tokens[1]), Double.Parse(tokens[2]), Double.Parse(tokens[3]), Double.Parse(tokens[4]), tokens[5], null);
                                }
                                else if (tokens.Length == 5)
                                {
                                    result = YelpSearchService.SearchBoundingBox(Double.Parse(tokens[1]), Double.Parse(tokens[2]), Double.Parse(tokens[3]), Double.Parse(tokens[4]), null, null);
                                }

                                break;
                            case "radius":
                                if (tokens.Length == 6)
                                {
                                    result = YelpSearchService.SearchRadius(Double.Parse(tokens[1]), Double.Parse(tokens[2]), Double.Parse(tokens[3]), tokens[4], tokens[5]);
                                }
                                else if (tokens.Length == 5)
                                {
                                    result = YelpSearchService.SearchRadius(Double.Parse(tokens[1]), Double.Parse(tokens[2]), Double.Parse(tokens[3]), tokens[4], null);
                                }
                                else if (tokens.Length == 4)
                                {
                                    result = YelpSearchService.SearchRadius(Double.Parse(tokens[1]), Double.Parse(tokens[2]), Double.Parse(tokens[3]), null, null);
                                }

                                break;
                            case "location":
                                if (tokens.Length == 5)
                                {
                                    result = YelpSearchService.SearchLocation(tokens[1], Double.Parse(tokens[2]), tokens[3], tokens[4]);
                                }
                                else if (tokens.Length == 4)
                                {
                                    result = YelpSearchService.SearchLocation(tokens[1], Double.Parse(tokens[2]), tokens[3], null);
                                }
                                else if (tokens.Length == 3)
                                {
                                    result = YelpSearchService.SearchLocation(tokens[1], Double.Parse(tokens[2]), null, null);
                                }

                                break;
                            case "neighborhood":
                                if (tokens.Length == 2)
                                {
                                    result = YelpSearchService.SearchHood(tokens[1]);
                                }

                                break;
                            case "help":
                                helpCommand = true;
                                break;
                            case "exit":
                            case "quit":
                            case "bye":
                                return;
                        }

                        if (result != null)
                        {
                            Console.WriteLine("Response Code: " + ((Int32)result.Message.Code).ToString() + " - " + result.Message.Code.ToString());
                            Console.WriteLine("Message: " + result.Message.Text);
                            Console.WriteLine();

                            foreach (Business entry in result.Businesses)
                            {
                                Console.WriteLine(entry.Name + ' ' + entry.Address1);
                                foreach (Review rev in entry.Reviews)
                                {
                                    //Console.WriteLine(rev.Excerpt);
                                }
                            }
                        }
                        else if (helpCommand)
                        {
                            if (tokens.Length == 1)
                            {
                                Console.WriteLine("box - Search for businesses within a bounding box.");
                                Console.WriteLine("radius - Search for businesses within a radius from a point.");
                                Console.WriteLine("location - Search for businesses near a named location.");
                                Console.WriteLine("help - Prints this listing, or the help for a specific command.");
                            }
                            else
                            {
                                switch (tokens[1].ToLower())
                                {
                                    case "box":
                                        Console.WriteLine("box top_lat left_long bottom_lat right_long category term");
                                        break;
                                    case "radius":
                                        Console.WriteLine("radius lat long radius category term");
                                        break;
                                    case "location":
                                        Console.WriteLine("location location radius category term");
                                        break;
                                }
                            }
                        }
                        else
                        {
                            Console.WriteLine("Command Not Recognized.");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("An Error Occurred");
                        Console.WriteLine(ex.ToString());
                    }

                    Console.WriteLine();
                }

                Console.Write("> ");
                line = Console.ReadLine();
            }
        }

        private static String[] Tokenize(String line)
        {
            List<String> tokens = new List<String>();

            Boolean escape = false;
            Boolean quoted = false;
            Char quoteChar = '\0';
            Int32 start = 0;

            for (Int32 i = 0; i < line.Length; i++)
            {
                if (quoted)
                {
                    if (!escape)
                    {
                        if (line[i] == quoteChar)
                        {
                            if (i - start - 1 > 0)
                            {
                                tokens.Add(line.Substring(start, i - start - 1));
                            }
                            else
                            {
                                tokens.Add(String.Empty);
                            }

                            quoted = false;
                            start = i + 1;
                        }
                        else if (i + 1 == line.Length)
                        {
                            if (i - start + 1 > 0)
                            {
                                tokens.Add(line.Substring(start, i - start + 1));
                            }
                        }
                        else if (line[i] == '\\')
                        {
                            escape = true;
                        }
                    }
                    else
                    {
                        escape = false;
                    }
                }
                else
                {
                    if (i == start && line[i] == '\'' || line[i] == '"')
                    {
                        quoted = true;
                        quoteChar = line[i];
                        start = i + 1;
                    }
                    else if (Char.IsWhiteSpace(line[i]))
                    {
                        if (i > start)
                        {
                            tokens.Add(line.Substring(start, i - start)); 
                        }

                        start = i + 1;
                    }
                    else if (i + 1 == line.Length)
                    {
                        if (i > start)
                        {
                            tokens.Add(line.Substring(start, i - start + 1));
                        }

                        start = i + 1;
                    }
                }
            }

            return tokens.ToArray();
        }
    }
}
